package org.chen.mvc.factory;

import org.chen.mvc.annotation.Controller;
import org.chen.mvc.annotation.GetMapping;
import org.chen.mvc.annotation.PostMapping;
import org.chen.mvc.annotation.RequestMapping;
import org.chen.spring.core.factory.BeanFactory;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 控制器工厂
 *
 * @author Chen
 * @since 2023/6/7 19:55
 */
public class ControllerFactory {

    private  final ConcurrentHashMap<String, Object> controllerMap = new ConcurrentHashMap<>();

    private  final ConcurrentHashMap<String, Method> methodMap = new ConcurrentHashMap<>();


    /**
     * 注册控制器
     *
     * @param clazz 控制器类
     */
    public  void register(Class<?> clazz) {
        if (clazz.isAnnotationPresent(Controller.class)) {
            StringBuilder typePath = new StringBuilder();
            String tempTypePath;
            if (clazz.isAnnotationPresent(RequestMapping.class)) {
                String value = clazz.getAnnotation(RequestMapping.class).value();
                typePath = new StringBuilder(value);
                if (!controllerMap.isEmpty() && controllerMap.containsKey(typePath.toString())) {
                    throw new RuntimeException("控制器路径不能重复");
                }
                if (!"".equals(value)) {
                    try {
                        controllerMap.put(value,
                                clazz.getDeclaredConstructor().newInstance());
                    } catch (InstantiationException | IllegalAccessException | InvocationTargetException |
                             NoSuchMethodException e) {
                        throw new RuntimeException(e);
                    }
                }

            }
            tempTypePath = typePath.toString();
            for (Method method : clazz.getDeclaredMethods()) {
                String methodPath;
                for (Annotation annotation : method.getDeclaredAnnotations()) {
                    Class<? extends Annotation> type = annotation.annotationType();
                    if (type == RequestMapping.class) {
                        methodPath = ((RequestMapping) annotation).value();
                    } else if (type == org.chen.mvc.annotation.GetMapping.class) {
                        methodPath = ((GetMapping) annotation).value();
                    } else if (type == PostMapping.class) {
                        methodPath = ((PostMapping) annotation).value();
                    } else {
                        continue;
                    }

                    if (methodPath == null) {
                        break;
                    }

                    if ("".equals(methodPath)) {
                        methodPath = "/";
                    }
                    if (methodPath.contains("*")) {
                        throw new RuntimeException("控制器路径不能包含*");
                    }
                    if (!methodPath.startsWith("/")) {
                        methodPath = "/" + methodPath;
                    }
                    //处理请求路径
                    if (typePath.toString().endsWith("/") && methodPath.startsWith("/")) {
                        methodPath = methodPath.substring(1);
                    }
                    methodMap.put(typePath.append(methodPath).toString(), method);
                    typePath = new StringBuilder(tempTypePath);
                }
            }
        }

    }

    public  Method getMethod(String path) {
        return methodMap.get(path);
    }

    /**
     * 注册所有控制器
     */
    public static void init() {
        BeanFactory.registerBean(ControllerFactory.class.getSimpleName(), new ControllerFactory());
        BeanFactory.resisterScanBean(new ControllerScanBean("org.chen.mvc.controller"));
    }
}
